﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace WPFByCoreApp
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            int intValue = 566;

            byte[] bytes = new byte[4];

            bytes[0] = (byte)(intValue >> 24);
            bytes[1] = (byte)(intValue >> 16);
            bytes[2] = (byte)(intValue >> 8);
            bytes[3] = (byte)intValue;

            Debug.WriteLine("{0} breaks down to : {1} {2} {3} {4}",
                intValue, bytes[0], bytes[1], bytes[2], bytes[3]);


            base.OnStartup(e);

            ///TestException.Test();

            //TestConcurrentDictionary.Test();


            //Check();


            this.DispatcherUnhandledException += AppUI_DispatcherUnhandledException;
            this.Dispatcher.UnhandledException += Dispatcher_UnhandledException;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;

        }

        /// <summary>
        /// FirstChanceException是一个异常通知事件。当一个AppDomain中引发任何异常的时候，CLR会优先触发FirstChanceException, 当其被处理后，才会开始寻找原始异常的处理函数。
        /// 在被catch捕获前就会触发，理论上可捕获所有异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
        {
            MiniDump.TryDump(@"D:\dump\CurrentDomain_FirstChanceException.dmp");
        }


        /// <summary>
        /// AppDomain.CurrentDomain.UnhandledException的CurrentDomain_UnhandledException方法将处理任何线程抛出的所有其他异常
        /// 经测试不能捕获Task异常，需要在AppDomain.CurrentDomain.FirstChanceException来捕获异常
        /// 捕获线程中的异常，当发生会不停的进入此方法，比如引发此异常：
        /// ThreadPool.QueueUserWorkItem((arg) =>
        /// {
        ///     string str = null;
        ///     var temp = str.ToString();
        /// });
        /// </summary>
        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            MiniDump.TryDump(@"D:\dump\CurrentDomain_UnhandledException.dmp");
        }



        ///< summary>
        ///捕获在主UI线程上抛出的未处理的异常，并允许
        ///选项用于用户继续程序。
        ///下面的AppDomain.CurrentDomain.UnhandledException的CurrentDomain_UnhandledException方法将处理任何线程抛出的所有其他异常。
        ///< / summary>
        private void AppUI_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            MiniDump.TryDump(@"D:\dump\App_DispatcherUnhandledException.dmp");

            //true:继续执行，false:退出程序。默认值false
            e.Handled = true;
        }

        ///< summary>
        ///捕获未被主UI线程抛出的未处理的异常。
        /// DispatcherUnhandledException的上述AppUI_DispatcherUnhandledException方法只会处理主UI线程抛出的异常。
        ///此方法捕获的未处理异常通常终止运行时。
        ///< / summary>
        private void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            MiniDump.TryDump(@"D:\dump\Dispatcher_UnhandledException.dmp");

        }


        private void Check()
        {

            int index = 1;
            Task.Run(delegate
            {
                while (true)
                {

                    //byte[] buffer = new byte[1000 * 1000];


                    //GCHandle hander = GCHandle.Alloc(buffer);
                    //var pin = GCHandle.ToIntPtr(hander);
                    //Debug.WriteLine("BeginInvoke之前：" + pin);


                    string str = "qx" + index;

                    this.Dispatcher.BeginInvoke((Action)delegate
                    {
                        //GCHandle hander = GCHandle.Alloc(buffer);
                        //var pin = GCHandle.ToIntPtr(hander);
                        Debug.WriteLine("BeginInvoke之后：" + str);

                        Thread.Sleep(1000);
                    });

                    index++;

                    Thread.Sleep(25);
                }
            });

        }

    }
}
